package chpt05;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;

public class MethodReferenceTest {

	/**
	 * 对validator验证通过的元素e使用mapper处理得到r，最后使用consumer处理r。
	 * 
	 * @param <T>
	 * @param <R>
	 * @param arr
	 * @param validator
	 * @param mapper
	 * @param consumer
	 */
	public static <T, R> void processArr(T[] arr, 
			Predicate<T> validator, 
			Function<T, R> mapper, 
			Consumer<R> consumer) {
		for (T e : arr) {
			if (validator.test(e)) {
				R r = mapper.apply(e);
				consumer.accept(r);
			}
		}
	}

	/**
	 * 对validator验证通过的元素e获取其中的给定值，最后使用consumer处理。
	 * 
	 * @param <T>
	 * @param arr
	 * @param validator
	 * @param supplier
	 * @param consumer
	 */
	public static <T> void processArr(T[] arr, Predicate<T> validator, Supplier<T> supplier, Consumer<T> consumer) {
		for (T e : arr) {
			if (validator.test(e)) {
				T t = supplier.get();
				consumer.accept(t);
			}
		}
	}

	/**
	 * 对String数组arr应用function得到的值拼接起来交由consumer处理
	 * 
	 * @param arr
	 * @param function
	 * @param consumer
	 */
	public static void processString(String[] arr, Function<String, String> function, Consumer<String> consumer) {
		String x = "";
		for (String e : arr) {
			x += function.apply(e);
		}
		consumer.accept(x);
	}

	public static void main(String[] args) {

		/* 测试1：普通方法引用测试*/
		methodReferenceTest();
		// 演示：构造器引用1
		consturctorMethodReferenceTest();
		// 演示：构造器引用2(使用标准函数式接口)
		Double[] arr = { -1.0, 9.0, 25.0, 0.0, -25.0 };
		class Foo {
			private double salary;

			public Foo(double salary) {
				this.salary = salary;
			}

			@Override
			public String toString() {
				return "Foo [salary=" + salary + "]";
			}
		}
		processArr(arr, e -> e >= 0, Foo::new, System.out::println);
		String[] numStrs = {"123","123.8", null};
		List<String> strList = Arrays.asList(numStrs);
		List<Double> list = strList.stream().filter(e->e!=null).map(Double::new).collect(Collectors.toList());

	}

	private static void methodReferenceTest() {
		Double[] arr = { -1.0, 9.0, 25.0, 0.0, -25.0 };
		// 全部使用lambda表达式进行匹配
		processArr(arr, t -> t >= 0, t -> Math.sqrt(t), r -> System.out.println(r));

		// lambda表达式、类名::静态方法、对象名::实例方法
		processArr(arr, e -> e >= 0, Math::sqrt, System.out::println);

		// 类名::实例方法（非静态方法）。
		String[] strArr = { "  abc  ", " def ", null, "ghijk  ", " " };
		processArr(strArr, Objects::nonNull, String::trim, System.out::print);
		System.out.println();
		processString(strArr, String::trim, System.out::print);
		System.out.println();
		// 实例方法引用
		Predicate<Double> validator = new Predicate<Double>() {
			@Override
			public boolean test(Double t) {
				return t >= 0;
			}
		};
		processArr(arr, validator, Math::sqrt, System.out::println);
		processArr(arr, validator::test, Math::sqrt, System.out::println);

		// Predicate作为目标类型被lambda表达式匹配
		Predicate<Double> validator2 = e -> e >= 0;
		processArr(arr, validator2, Math::sqrt, System.out::println);
		// 演示：类名::实例方法
		String[] names = { "zhang", "wang", "zhaoli", "li",
			    "sun", "chen", "wu", "bo" };
		Arrays.sort(names, String::compareToIgnoreCase);
		System.out.println(Arrays.toString(names));
		

	}
	
	@FunctionalInterface
	interface ICreatePerson {
		Person createPerson(String name, int id);
	}

	// 构造器引用
	private static void consturctorMethodReferenceTest() {
		
		// ICreatePerson foo = (name, id)->new Person(name, id);
		ICreatePerson foo = Person::new;
		Person person = foo.createPerson("zhang", 1);
		ArrayList<String> arrList = new ArrayList<>();
		//数组类型的使用构造器引用

	}

}
